כל מערכת מורכבת משלושה חלקים: הנתונים, העיצוב שבו הם מוצגים והמנגן של התזמורת – זה שמחליט איזה נתונים ובאיזה עיצוב להציג.
11.08.2012 המדריך כרגע בעריכה, לכן החלק על המודל חסר בו.
עמכם הסליחה
יש משהו קטן ומעצבן שהורס כל קוד והוא דווקא ה-HTML. בגללו יש הרבה סוגריים מסולסלים, פתיחות וסגירות תגי PHP והרבה קטעים מסורבלים ובלתי קשורים שמפריעים לעין ולהבנת הקוד.
במאמר הזה אני רוצה להכיר לכם את ההפרדה של PHP מכל מה שמסביבו. נראה איך אנחנו מפיקים את המיטב מתבנית העיצוב Model Viewer Controller ומה זה הדינוזאור הזה בכלל.
מה זה MVC (Model Viewer Controller)?
נסתכל לרגע על התוכנית שלנו ונפשט אותה מעט.
אנחנו צריכים לקבל נתון מהלקוח, לעשות איתו משהו ולהציג תוצאה כלשהי בתוך עיצוב כלשהו. למשל, כדי להציג את העמוד הספציפי הזה, הסקריפט היה צריך לקבל מאיתנו את שם העמוד המבוקש, לשלוף את תוכנו מהמסד ולהציג אותו בעיצוב של האתר.
מה היה קורה אילו היינו מבקשים עמוד אחר? הסקריפט היה צריך לקבל את שם העמוד, לשלוף תוכן שונה הפעם, אבל להציג באותו עיצוב. ואם הייתם מבצעים חיפוש באתר, הפעם היה נכנס לפעולה סקריפט אחר שעושה חיפוש במסד, אבל עדיין מציג את הכל באותו עיצוב.
view
העיצוב הקבוע של האתר הוא ה-view – תבנית התצוגה שבה יראו הנתונים. הנתונים תמיד יראו מתחת לתפריט העליון ובצד אחד של העמוד, כאשר בצד השני יהיה תפריט צד. תבנית התצוגה קבוע לכל האתר ומכילה הרבה קוד html כללי. שלא שייך ספציפית למדריך הזה, או לתוצאות החיפוש או לשום דבר אחר.
דבר אחד ברור לנו: ה-view חוזר על עצמו בין עמוד לעמוד.
גם בעמוד תצוגת מדריך וגם בעמוד תוצאות חיפוש. מה שאומר שעכשיו ניצור שני סקריפטים, שכל אחד מהם מייצר את אותו קוד html סופי עם חלק קטן שונה באמצע.
סקריפט שמציג מדריך - יציג תפריט עליון, תפריט צד, תפריט תחתון ואת המדריך.
סקריפט שמציג חיפוש - יציג תפריט עליון, תפריט צד, תפריט תחתון ואת תוצאות החיפוש.
רואים את ההבדל? ומה קורה עם יש לנו כמה עמודים שונים באתר שמוצגים באותה תבנית?
עמוד ראשי, עמוד שאלונים, עמוד שאלות תשובות, עמוד phplive, עמוד מידע, עמוד יצירת קשר, עמוד..
בכל אחד מהם נצטרך לכתוב את אותו ה-html שמציג תפריט עליון, תפריט צד, תפריט תחתון ורק משהו קטן ישתנה באמצע בין עמוד לעמוד.
עד כאן הכל נראה לנו בסדר - הרי יש כפתור copy paste במקלדת.
הבעיה מתחילה ברגע שבו מגיעה הזמן להוסיף עוד סעיף לתפריט העליון. פתאום מסתבר לנו שצריך לערוך 10-15 קבצים בשביל להכניס עוד כפתור לתפריט. וכנראה זה לא השינוי היחיד שצפוי לאתר שיגדל עם הזמן.
מפרידים את ה view מהקונטרולר
הפתרון שעולה פשוט דייו. צריך לקחת את הקוד של התפריט העליון, להוציא אותו לקובץ חיצוני ואת התוכן המשתנה להכניס לתוכו. התוצאה שתתקבל תראה ככה:
SiteView.php
<html>
<head> ... </head>
<body>
<nav> .. </nav>
<?= $content ?>
<aside>...</aside>
</body>
<footer> ... </footer>
</html>
<head> ... </head>
<body>
<nav> .. </nav>
<?= $content ?>
<aside>...</aside>
</body>
<footer> ... </footer>
</html>
יצרנו את תבנית התצוגה הראשונה שלנו - siteview על ידי זה שהוצאנו את החלק שחוזר על עצמו (תבנית התצוגה) לקובץ נפרד. עכשיו נשאר לנו רק לגרום לתוכן להיות מוצג בתבנית הזו.
שימו לב למשתנה content באמצע התבנית. במקום משתנה זה יופיע התוכן האמיתי של העמוד. את התוכן הזה מישהו צריך להכניס לשם ואת התפקיד הזה מבצע הבקר, או בשמו האנגלי:
Controller
תפקידו של ה-controller הוא לנהל את העניינים. להחליט מה להציג, איך לעשות את זה, מה לחשב ואילו תבניות תצוגה להכליל בתוצאה הסופית. הקונטרולר הוא זה שמבצע את פעולות השליפה מהמסד, זה שעושה את החישובים, זה שמכניס נתונים, זה שבודק הרשאות ושם קוראת כל הלוגיקה של התכנה שלנו.
במילים פשוטות עליו להחליט מה יהיה התוכן של המשתנה content למעלה. האם זה יהיה תוכן המדריך, האם תוצאת החיפוש או סתם הודעה שהעמוד לא נמצא 404.
כדי לא לסבך את העניינים יותר מדי נבנה קונטרולר שמציג את השעה הנוכחית ויראה ככה:
TimeController.php
<?php
$content = date('H:i:s');
require 'SiteView.php';
?>
$content = date('H:i:s');
require 'SiteView.php';
?>
הפעולה של הקונטרולר פשוטה מאוד.
הקונטרולר מחליט מה יהיה בתוך המשתנה content ואחרי זה מציג את זה בתבנית התצוגה שלנו.
הקונטרולר יכול להחליט להציג תבנית תצוגה אחרת או תוכן אחר. הוא שולט על מה יהיה מוצג ובאיזה תבנית.
דוגמה לקוד של קונטרולר שמציג הודעות שונות בתצוגות שונות יכול להיראות ככה:
IndexController.php
<?php
if(isset($_GET['name']))
{
$content = 'Hi ' . htmlSpecialChars($_GET['name'], ENT_QUOTES, 'UTF-8');
require 'SiteView.php';
}
else
{
require '404.php';
}
?>
if(isset($_GET['name']))
{
$content = 'Hi ' . htmlSpecialChars($_GET['name'], ENT_QUOTES, 'UTF-8');
require 'SiteView.php';
}
else
{
require '404.php';
}
?>
במקרה שהוזן שם כלשהו - הקונטרולר יציג הודעת שלום בתבנית הרגילה של האתר.
אם לא - תוצג תבנית של דף 404 בלי הודעות מיוחדות.
כמו שאנחנו רואים - אין שום דבר על-תבעי בתבנית ה-MVC.
עד כאן היו ה (View) V וה- (Controller) C ועוד שלב אחד נשאר לנו במשוואה - הנתונים.
Model
11.08.2012 המדריך כרגע בעריכה, לכן החלק על המודל חסר בו.
עמכם הסליחה
תגובות לכתבה:
תודה רבה אלכס, חיפשתי מדריך לזה פעם, מזל שיש את האתר שלך :)
תודה רבה! מדריך מובן מאוד. אהבתי אותו.
תודה אלכסנדר
מדריך מאוד יפה :)
אחלה מדריך !!!!!!! D=
שאלה: יש לי דף CSS ואני רוצה לכתוב בו {LOGO} ושהמערכת תשנה את זה לקישור של התמונה של הלוגן: images/logo.jpg. איך אני עושה את זה? לא הצלחתי :/
<img src="images/logo.jpg" />
אני רוצה לכתוב
.logo {
background:url({LOGO_URL})
}
אם לא הבנת :/
או שאתה סתם מתחכם...
אממ לא, חשבתי שהתכוונת למשו אחר
וראיתי פעם מישו עשה link לדף PHP שהוא בעצם CSS
כלומר
<link rel="stylesheet" type="text/css" href="cssCode.php" />
בדף PHP תוכל לרשום פונקציית MVC מדף מודל כלשהוא..
תודה. יש עוד דרך? (יותר ישירה - בלי עוד דף PHP אלא CSS שהוא המודל ואותו משנים.
כמו שכתבתי שזה יהיה בדף CSS:
.logo {
background:url({LOGO_URL})
}
כן.
תוכל להעביר את הסטייל הזה בלבד לתוך חלק מ view כלשהו שלך שעליו כן מופעלות הטרנספורמציות
header.htm:
<html>
<title>{title}</title>
<link rel="stylesheet" type="text/css" href="cssCode.php" />
<style>
.logo {
background:url({LOGO_URL})
}
</style>
ראיתי בPHPBB שיש גם תנאים. לדוגמה:
<!-- IF S_DISPLAY_BIRTHDAY_LIST -->
ואח"כ לפי התנאים האלה מוצג התוכן.
איך הם עושים את זה?
זה משתמש_15228 (אני במקום אחר..)
אבל אם אני רוצה שזה יהיה בדף CSS?
אין אפשרות כזאת?
תלחץ על כפתור "בחר שם אחר" ויהיה לך שם זהה בכל מקום.
-----
אם אתה רוצה שזה יהיה בקובץ css עמצו אתה צריך שמיהשהו יעבור על התוכן של הקובץ ויכניס לתוכו את הערכים האלה במקום המתאים.
המישהו הזה זה הקוד שלך. ותצטרך להפעיל אותו על קובץ ה css. אני לא יודע עד כמה הלוגו שלך משתנה כל הזמן, אבל אם הוא שונה בכל עמוד אין סיבה שלא תוציא אותו מהקובץ css עצמו ככה שהקובץ תמיד יישמר ב cache של הדפדפן ואילו העמוד עצמו ייטען כל פעם מחדש עם המיקום המתאים
ב PHPBB משתמשים במשהו קצת יותר מתוחכם ממה שהוצג פה. יש פתרונות מוכנים ל Template Engine שמתוארים פה. האתר הזה השתמש ב twig-project.org שהוא מנוע התבניות המהיר ביותר שמצאתי.
הוא תומך גם בלולאות ובתנאים ובמליון דברים אחרים.
כמובן יש לך גם את smarty שאמנם יותר איטי אבל יותר פופולארי. אליהו בסה כתב עליו אחלה הסבר כאן:
http://phpguide.co.il/Smarty_Template_Engine.htm
בחרתי שם חדש :)
_____________________
אוקי תודה לך על התשובה.
אני מצטער שאני מעצבן אבל יש לי עוד שאלה P:
איך הם עושים שהשורה הזאת:
<!-- INCLUDE overall_header.html -->
מוסיפה את הדף overall_header.html? או שזה גם יותר מורכב?
זה גם יותר מורכב, אבל כזה לא אמור להיות לך בעיה לעשות לבד. בסה"כ צריך לכתוב ביטוי רגולרי שיימצא מחרוזות שמתחילות במילה אינקלוד, יוציא מההמשך את שם הקובץ ויפעיל את הפונקציה viewer עליו.
שוב, תוכל בתור תרגול לכתוב אחת כזאת משלך. הקוד בכתבה בסה"כ בא להכיר לקורא את התיאוריה וקצת להדגים אותה. כדי לעבוד בשיטה הזאת רצוי שתשתמש ב twig-project.org או smarty
אלכס, יש לי משתנה שהוא בעצם מערך שמכיל בתוכו כמה טקסטים איך אני יכול לפלוט את זה לMVC HTML?
בשביל מערך אתה צריך מבנה כלשהו שיודע לעבוד בלולאה עם מערך.
באופן כללי המנוע תבניות המבוסס replaceים שכתבנו כאן היה לצורך הדגמה בלבד. אתה יכול להישתמש ב twig או ב smarty שבהם יש תמיכה להרבה דברים מגניבים שונים בתוך הview, כולל לולאות, תנאים ועוד
תוכל לתת לי רעיון איך לעשות את המבנה של הVIEW? אני לא רוצה להתעסק עם מנועים אחרים..
אם אתה לא רוצה להתעסק במנועים אחרים, יש לך שני חלופות:
להעסק בטוקניזציה ופיענוח לקסי של התבנית (הפרדה של הקובץ למילים והרכבת לוגיקה מהם, כמו שמפענח ה PHP עושה על קבצי קוד )
או להתעסק בביטויים רגולריים ובעיות ביצועים.
הראשון מסתכם בלקרוא 3 עמודים באנגלית, כששניים מהם לא חובה
שני האופציות האחרות בהרבה שעות של כאב ראש.
רשימת קישורים בהתאם:
---------------------------
1. http://twig-project.org
2. http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html
3. http://phpguide.co.il/ביטויים_רגולריים.htm
מדריך מעולה, עזר לי המון! תודה רבה.
רק שאלה אחת:
"בכתבה הבאה אספר לכם על Twig Project, ה-Template Engine שיצר והציג את העמוד הזה." - איפה זה? :)
תודה שהחזרת אלכס, אני מחכה לעריכה בנתיים :-)
תודה רבה, רק חבל שאין Model
עובדים על זה :) אני אפרסם את המדריך מחדש תוך שבועיים.
יעלה model מתישהו :) ?
יש גם את RainTPL למערכת טמפטלים.. (בנוגע לבחורצ'ק שלא רצה להתשמש בסמארטי).
תזכירו לי מה עושים אלה שלא משתמשים ב-MVC... שכחתי. :-)
אלה שלא משתמשים, לומדים ומחכים לפרק על ה model :-)
קצת באיחור אבל מה עם החלק האחרון?